home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / adduser / RCS / common.c,v < prev    next >
Encoding:
Text File  |  1991-06-10  |  12.7 KB  |  676 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     91.06.10.12.08.33;  author kupfer;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     91.06.04.16.51.44;  author kupfer;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     91.06.03.17.08.54;  author kupfer;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     90.03.21.11.05.11;  author rab;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     90.03.01.12.21.12;  author rab;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @@
  37.  
  38.  
  39. 1.5
  40. log
  41. @Set the real uid to root early on, rather than trying to figure out
  42. which subprocesses (e.g., rsh) need to have real uid == effective uid.
  43. @
  44. text
  45. @/* 
  46.  * common.c --
  47.  *
  48.  *    Collect infomation on a new account request.
  49.  *      Make sure the information is valid.  Then mail it
  50.  *      to the staff.
  51.  *
  52.  * Copyright 1990 Regents of the University of California
  53.  * Permission to use, copy, modify, and distribute this
  54.  * software and its documentation for any purpose and without
  55.  * fee is hereby granted, provided that the above copyright
  56.  * notice appear in all copies.  The University of California
  57.  * makes no representations about the suitability of this
  58.  * software for any purpose.  It is provided "as is" without
  59.  * express or implied warranty.
  60.  */
  61.  
  62. #ifndef lint
  63. static char rcsid[] = "$Header: /sprite/src/admin/adduser/RCS/common.c,v 1.4 91/06/04 16:51:44 kupfer Exp Locker: kupfer $";
  64. #endif
  65.  
  66. #include "common.h"
  67. #include <sprite.h>
  68. #include <ctype.h>
  69. #include <errno.h>
  70. #include <fcntl.h>
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <string.h>
  74. #include <sys/ioctl.h>
  75. #include <sys/param.h>
  76. #include <sys/types.h>
  77. #include <sys/wait.h>
  78. #include <time.h>
  79. #include <unistd.h>
  80.  
  81. /* Forward references: */
  82. #if 0
  83. static void mail _ARGS_((CONST char *whom, CONST char *msg));
  84. #endif
  85.  
  86.  
  87. /*
  88.  *----------------------------------------------------------------------
  89.  *
  90.  * raw_getchar --
  91.  *
  92.  *    Get a character in cbreak mode, without waiting for a carriage
  93.  *      return.
  94.  *
  95.  * Results:
  96.  *    Returns the character read, or EOF if no more input is available.
  97.  *
  98.  * Side effects:
  99.  *    None.
  100.  *
  101.  *----------------------------------------------------------------------
  102.  */
  103.  
  104. int
  105. raw_getchar()
  106. {
  107.     struct sgttyb sgtty_buf;
  108.     int c;
  109.  
  110.     ioctl(fileno(stdin), TIOCGETP, &sgtty_buf);
  111.     sgtty_buf.sg_flags |= CBREAK;
  112.     ioctl(fileno(stdin), TIOCSETP, &sgtty_buf);
  113.     c = getchar();
  114.     sgtty_buf.sg_flags &= ~CBREAK;
  115.     ioctl(fileno(stdin), TIOCSETP, &sgtty_buf);
  116.     return c;
  117. }
  118.  
  119.  
  120. /*
  121.  *----------------------------------------------------------------------
  122.  *
  123.  * yes --
  124.  *
  125.  *    Get a yes/no response from the user.
  126.  *
  127.  * Results:
  128.  *    1 if the user said yes, 0 if no.
  129.  *
  130.  * Side effects:
  131.  *    None.
  132.  *
  133.  *----------------------------------------------------------------------
  134.  */
  135.  
  136. int
  137. yes(prompt)
  138.     char *prompt;
  139. {
  140.     int x;
  141.  
  142.     for (;;) {
  143.     printf("\n%s  (y or n) ", prompt);
  144.     x = raw_getchar();
  145.     printf("\n");
  146.     switch (x) {
  147.  
  148.     case 'y':
  149.     case 'Y':
  150.         x = 1;
  151.         break;
  152.  
  153.     case 'n':
  154.     case 'N':
  155.         x = 0;
  156.         break;
  157.  
  158.     default:
  159.         continue;
  160.     }
  161.     break;
  162.     }
  163.     return x;
  164. }
  165.  
  166. void
  167. getString(forbid, prompt, string)
  168.     CONST char *forbid;
  169.     CONST char *prompt;
  170.     char *string;
  171. {
  172.     char buffer[BUFFER_SIZE];
  173.     CONST char *f;
  174.  
  175.     for (;;) {
  176.     printf(string[0] ? "%s(%s): " : "%s: ", prompt, string);
  177.     fgets(buffer, BUFFER_SIZE - 1, stdin);
  178.     if (buffer[strlen(buffer) - 1] == '\n') {
  179.         buffer[strlen(buffer) - 1] = '\0';
  180.     }
  181.     if (buffer[0] != '\0') {
  182.         strcpy(string, buffer);
  183.     }
  184.     for (f = forbid;; ++f) {
  185.         if (*f == '\0') {
  186.         return;
  187.         }
  188.         if (strchr(buffer, *f)) {
  189.         fprintf(stderr, "This entry cannot contain a `%c'!\n", *f);
  190.         break;
  191.         }
  192.     }
  193.     }
  194. }
  195.  
  196. void
  197. getPasswd(p)
  198.     char *p;
  199. {
  200.     char passwd1[BUFFER_SIZE];
  201.     char passwd2[BUFFER_SIZE];
  202.     static char salt_chars[] = 
  203.       "./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  204.     static char salt[3];
  205.     int c;
  206.     struct sgttyb sgtty_buf;
  207.  
  208.     printf("Press 1 to enter an encrypted passwd\n");
  209.     printf("Press 2 to enter a plaintext passwd\n");
  210.     printf("Press 3 to leave this field blank\n");
  211.     for (;;) {
  212.     printf("Please enter 1, 2 or 3: ");
  213.     c = raw_getchar();
  214.     printf("\n");
  215.     switch (c) {
  216.  
  217.     case '1':
  218.         getString("", "Enter encrypted passwd", p);
  219.         if ((strlen(p) != 13) || strspn(p, salt_chars) != 13) {
  220.         printf("%s is not a valid encrypted password!\n", passwd1);
  221.         printf("Please try again.\n");
  222.         continue;
  223.         }
  224.         return;
  225.  
  226.     case '2':
  227.         passwd1[0] = '\0';
  228.         passwd2[0] = '\0';
  229.         ioctl(0, TIOCGETP, &sgtty_buf);
  230.         sgtty_buf.sg_flags &= ~ECHO;
  231.         ioctl(0, TIOCSETP, &sgtty_buf);
  232.         getString("", "Password", passwd1);
  233.         printf("\n");
  234.         getString("", "Retype passwd", passwd2);
  235.         printf("\n");
  236.         if (*passwd1 == '\0' || strcmp(passwd1, passwd2) != 0) {
  237.         printf("Sorry, try again\n");
  238.         continue;
  239.         }
  240.         sgtty_buf.sg_flags |= ECHO;
  241.         ioctl(0, TIOCSETP, &sgtty_buf);
  242.         srandom(time(0));
  243.         salt[0] = salt_chars[random() % sizeof(salt_chars)];
  244.         salt[1] = salt_chars[random() % sizeof(salt_chars)];
  245.         strcpy(p, crypt(passwd1, salt));
  246.         return;
  247.  
  248.     case '3':
  249.         strcpy(p, "*");
  250.         return;
  251.  
  252.     default:
  253.         continue;
  254.     }
  255.     }
  256. }
  257.  
  258. char *
  259. getShell()
  260. {
  261.     int c;
  262.  
  263.     printf("Please select a shell\n");
  264.     printf("\t1  csh (default)\n");
  265.     printf("\t2  tcsh\n");
  266.     printf("\t3  sh\n");
  267.     for (;;) {
  268.     printf("Please enter 1, 2 or 3: ");
  269.     c = raw_getchar();
  270.     printf("\n");
  271.     switch (c) {
  272.  
  273.     case '1':
  274.     case '\n':
  275.         return "/sprite/cmds/csh";
  276.  
  277.     case '2':
  278.         return "/sprite/cmds/tcsh";
  279.  
  280.     case '3':
  281.         return "/sprite/cmds/sh";
  282.  
  283.     default:
  284.         continue;
  285.     }
  286.     }
  287. }
  288.  
  289. #if 0
  290. static void
  291. mail(whom, msg)
  292.     CONST char *whom;
  293.     CONST char *msg;
  294. {
  295.     int pipeFd[2];
  296.     int childPid;
  297.     int w;
  298.  
  299.     pipe(pipeFd);
  300.     switch (childPid = fork()) {
  301.  
  302.     case -1:
  303.     fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
  304.     exit(1);
  305.  
  306.     case 0: /* child */
  307.     close(pipeFd[1]);
  308.     dup2(pipeFd[0], 0);
  309.     execlp("mail", "mail", whom, NULL);
  310.     fprintf(stderr, "Can't exec mail: %s\n", strerror(errno));
  311.     exit(1);
  312.  
  313.     default: /* parent */
  314.         close(pipeFd[0]);
  315.     if (write(pipeFd[1], msg, strlen(msg)) != strlen(msg)) {
  316.         fprintf(stderr, "Error writing to pipe: %s\n", strerror(errno));
  317.         exit(1);
  318.     }
  319.     close(pipeFd[1]);
  320.     while ((w = wait(0)) > 0 && w != childPid) {
  321.         continue;
  322.     }
  323.     printf("done sending mail\n");
  324.     break;
  325.     }
  326.     return;
  327. }
  328. #endif /* 0 */
  329.  
  330. void
  331. getNumber(prompt, buf)
  332.     CONST char *prompt;
  333.     char *buf;
  334. {
  335.  
  336.     for (;;) {
  337.     getString("", prompt, buf);
  338.     if (checkNumber(buf)) {
  339.         return;
  340.     }
  341.     fprintf(stderr, "Only digits [0-9] should be used!\n");
  342.     *buf = '\0';
  343.     }
  344. }
  345.  
  346. int
  347. checkNumber(buf)
  348.     char *buf;
  349. {
  350.     int i;
  351.  
  352.     for (i = strlen(buf); --i >= 0;) {
  353.     if (!isascii(buf[i]) || !isdigit(buf[i])) {
  354.         return 0;
  355.     }
  356.     }
  357.     return 1;
  358. }
  359.  
  360.  
  361. /*
  362.  *----------------------------------------------------------------------
  363.  *
  364.  * makedb --
  365.  *
  366.  *    Regenerate the hashed password file.
  367.  *
  368.  * Results:
  369.  *    0 for success, an exit status otherwise.
  370.  *
  371.  * Side effects:
  372.  *    Creates the .dir and .pag files to match the plain-text 
  373.  *    password file.
  374.  *
  375.  *----------------------------------------------------------------------
  376.  */
  377.  
  378. int
  379. makedb(file)
  380.     char *file;
  381. {
  382.     int status, pid, w;
  383.     
  384.     if (!(pid = vfork())) {
  385.     execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL);
  386.     (void) fprintf(stderr, "Can't exec %s: %s\n",
  387.                _PATH_MKPASSWD, strerror(errno));
  388.     _exit(127);
  389.     }
  390.     while ((w = wait(&status)) != pid && w != -1) {
  391.     continue;
  392.     }
  393.     return(w == -1 || status);
  394. }
  395.  
  396.  
  397. /*
  398.  *----------------------------------------------------------------------
  399.  *
  400.  * rcsCheckOut --
  401.  *
  402.  *    Check out a file.
  403.  *
  404.  * Results:
  405.  *    Returns the exit status of the "co" invocation, or -1 if there 
  406.  *    was a system error (and co couldn't be run).
  407.  *
  408.  * Side effects:
  409.  *    Checks out the file.
  410.  *
  411.  *----------------------------------------------------------------------
  412.  */
  413. int
  414. rcsCheckOut(file)
  415.     char *file;
  416. {
  417.     int child;
  418.     union wait ws;
  419.     int w;
  420.  
  421.     switch (child = fork()) {
  422.  
  423.     case -1:
  424.     fprintf(stderr, "Fork failed: %s\n", strerror(errno));
  425.     return -1;
  426.     case 0:
  427.     execlp("co", "co", "-l", file, NULL);
  428.     fprintf(stderr, "Cannot exec co: %s\n", strerror(errno));
  429.     exit(EXIT_FAILURE);
  430.     default:
  431.     while ((w = wait(&ws)) > 0 && w != child) {
  432.         continue;
  433.     }
  434.     return ws.w_retcode;
  435.     }
  436. }
  437.  
  438.  
  439. /*
  440.  *----------------------------------------------------------------------
  441.  *
  442.  * rcsCheckIn --
  443.  *
  444.  *    Check in a file.
  445.  *
  446.  * Results:
  447.  *    Returns the exit code of the "ci" invocation, or -1 if there 
  448.  *    was a system error (and ci couldn't be run).
  449.  *
  450.  * Side effects:
  451.  *    Checks in the file, whether or not it had actually changed.
  452.  *
  453.  *----------------------------------------------------------------------
  454.  */
  455. int
  456. rcsCheckIn(file, logMsg)
  457.     char *file;            /* file to check in */
  458.     char *logMsg;        /* message for the RCS log, with 
  459.                  * leading -m */
  460. {
  461.     int child;
  462.     union wait ws;
  463.     int w;
  464.  
  465.     switch (child = fork()) {
  466.     case -1:
  467.     fprintf(stderr, "Fork failed: %s\n", strerror(errno));
  468.     return -1;
  469.     case 0:
  470.     dup2(open("/dev/null", O_RDONLY), 0);
  471.     execlp("ci", "ci", logMsg, "-f", "-u", file, NULL);
  472.     fprintf(stderr, "Cannot exec ci: %s\n", strerror(errno));
  473.     exit(EXIT_FAILURE);
  474.     default:
  475.     while ((w = wait(&ws)) > 0 && w != child) {
  476.         continue;
  477.     }
  478.     return ws.w_retcode;
  479.     }
  480. }
  481.  
  482.  
  483. /*
  484.  *----------------------------------------------------------------------
  485.  *
  486.  * SecurityCheck --
  487.  *
  488.  *    Verify that we're running as root.  Make the real ID and 
  489.  *    effective ID both be root.
  490.  *    
  491.  *    The real ID is made root to avoid problems with subprocesses 
  492.  *    that exec random programs and act differently if the effective 
  493.  *    ID is different from the real ID.  This is not a security 
  494.  *    problem, because the program is installed so that only root or 
  495.  *    wheels can run it.
  496.  *
  497.  * Results:
  498.  *    None.
  499.  *
  500.  * Side effects:
  501.  *    Exits if any of the checks fail.
  502.  *
  503.  *----------------------------------------------------------------------
  504.  */
  505.  
  506. void
  507. SecurityCheck()
  508. {
  509.     if (setreuid(0, 0) < 0) {
  510.     perror("Can't setuid to root");
  511.     fprintf(stderr,
  512.         "Check whether the program was correctly installed.\n");
  513.     exit(EXIT_FAILURE);
  514.     }
  515. }
  516. @
  517.  
  518.  
  519. 1.4
  520. log
  521. @Make sure the invoking user is in the wheel group.
  522. @
  523. text
  524. @d19 1
  525. a19 1
  526. static char rcsid[] = "$Header: /sprite/src/admin/adduser/RCS/common.c,v 1.3 91/06/03 17:08:54 kupfer Exp Locker: kupfer $";
  527. a26 1
  528. #include <grp.h>
  529. d444 8
  530. a451 2
  531.  *    Verify that we're running as root and that the user is in the 
  532.  *    wheel group.
  533. d465 2
  534. a466 23
  535.     int groupList[NGROUPS];    /* groups that the user belongs to */
  536.     int numGroups;        /* number of groups the user is in */
  537.     struct group *wheel;    /* info about the wheel group */
  538.     int group;            /* index into groupList */
  539.  
  540.     if (geteuid() != 0) {
  541.     fprintf(stderr,
  542. "Not running as root.  Check whether the program was correctly installed.\n");
  543.     exit(EXIT_FAILURE);
  544.     }
  545.  
  546.     wheel = getgrnam("wheel");
  547.     if (wheel == NULL) {
  548.     fprintf(stderr, "No wheel group?!\n");
  549.     exit(EXIT_FAILURE);
  550.     }
  551.     numGroups = getgroups(NGROUPS, groupList);
  552.     for (group = 0; group < numGroups; group++) {
  553.     if (groupList[group] == wheel->gr_gid) {
  554.         break;
  555.     }
  556.     }
  557.     if (group == numGroups) {
  558. d468 1
  559. a468 1
  560.         "Sorry, you must be in the wheel group to run this program.\n");
  561. @
  562.  
  563.  
  564. 1.3
  565. log
  566. @More routines shared with deleteuser.  Check whether the RCS checkout
  567. succeeded.  Lint.  Better support for testing.  Give an RCS log
  568. message when checking a file in.
  569. @
  570. text
  571. @d19 1
  572. a19 1
  573. static char rcsid[] = "$Header: /sprite/src/admin/adduser/RCS/common.c,v 1.2 90/03/21 11:05:11 rab Exp Locker: kupfer $";
  574. d27 1
  575. d32 2
  576. d436 50
  577. @
  578.  
  579.  
  580. 1.2
  581. log
  582. @*** empty log message ***
  583. @
  584. text
  585. @d19 1
  586. a19 1
  587. static char rcsid[] = "$Header: /sprite/src/admin/adduser/RCS/common.c,v 1.1 90/03/01 12:21:12 rab Exp $";
  588. d22 5
  589. d31 3
  590. d35 3
  591. a37 2
  592. #ifndef __STDC__
  593. #define const
  594. d40 17
  595. a56 1
  596. #define BUFFER_SIZE     0x100
  597. a57 8
  598. extern int errno;
  599. extern char *crypt();
  600.  
  601. extern int  yes();
  602. extern void getString();
  603. extern void getPasswd();
  604. extern void mail();
  605.  
  606. d64 1
  607. a64 1
  608.     ioctl(0, TIOCGETP, &sgtty_buf);
  609. d66 1
  610. a66 1
  611.     ioctl(0, TIOCSETP, &sgtty_buf);
  612. d69 1
  613. a69 1
  614.     ioctl(0, TIOCSETP, &sgtty_buf);
  615. d73 17
  616. d122 2
  617. a123 2
  618.     const char *forbid;
  619.     const char *prompt;
  620. d127 1
  621. a127 1
  622.     const char *f;
  623. d243 2
  624. a244 1
  625. void
  626. d246 2
  627. a247 1
  628.     const char *msg;
  629. d282 1
  630. d284 1
  631. a284 1
  632. int
  633. d286 1
  634. a286 1
  635.     const char *prompt;
  636. d307 1
  637. a307 1
  638.     if (!isdigit(buf[i])) {
  639. d314 121
  640. @
  641.  
  642.  
  643. 1.1
  644. log
  645. @Initial revision
  646. @
  647. text
  648. @d19 1
  649. a19 1
  650. static char rcsid[] = "$Header$";
  651. d38 1
  652. a38 1
  653. extern char *getPasswd();
  654. d116 3
  655. a118 2
  656. char *
  657. getPasswd()
  658. a131 2
  659.     passwd1[0] = '\0';
  660.     passwd2[0] = '\0';
  661. d138 2
  662. a139 2
  663.         getString("", "Enter encrypted passwd", passwd1);
  664.         if ((strlen(passwd1) != 13) || strspn(passwd1, salt_chars) != 13) {
  665. d144 1
  666. a144 1
  667.         return passwd1;
  668. d147 2
  669. d165 2
  670. a166 1
  671.         return crypt(passwd1, salt);
  672. d169 2
  673. a170 1
  674.         return "*";
  675. @
  676.